home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvi2qms / dvi.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  17KB  |  725 lines

  1. /* dvi.c The dvi reader for dvi printers.
  2.  * Copyright 1985 Massachusetts Institute of Technology.
  3.  * Author: cjl@oz
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include "fonts.h"
  10. #include "dev.h"
  11. #include "util.h"
  12. #include "dvi.h"
  13.  
  14. extern char *rindex();
  15. extern char *mktemp();
  16. extern long ftell();
  17.  
  18. #define DVI_STACK_SIZE      512    /* Maximum dvi stack size supported. */
  19. #define NFONTDIR_MAX         16
  20. #define MAXDRIFT          2
  21. #ifndef PXLDIR
  22. #define PXLDIR "/usr/lib/tex/pxlfonts"
  23. #endif
  24.  
  25. /* Runtime parameters specified by user
  26.  */
  27. FILE *out = stdout;
  28. FILE *in;
  29. char *dirvec[NFONTDIR_MAX];
  30. long start_page = -1000000;
  31. long end_page = 1000000;
  32. long usermag;
  33. int dirveclen;
  34. unsigned long devopts,fontopts;
  35.  
  36. /* Runtime parameters specified by the dvi file & the user
  37.  */
  38. char pre_comment[257];
  39. long numerator,denominator,half_denominator,dvinum,dviden,dvimag;
  40. long globalmag;
  41.  
  42.  
  43. /* Runtime data structures
  44.  */
  45. char stdoutbuf[BUFSIZ];
  46. long h_pix,v_pix,h,v,w,x,y,z,device_dpi,fntspc;
  47. unsigned long fntvec[512],chrvec[512][4];
  48. int stackptr,fntveclen;
  49. long hstack[DVI_STACK_SIZE];
  50. long h_pixstack[DVI_STACK_SIZE];
  51. long vstack[DVI_STACK_SIZE];
  52. long v_pixstack[DVI_STACK_SIZE];
  53. long wstack[DVI_STACK_SIZE];
  54. long xstack[DVI_STACK_SIZE];
  55. long ystack[DVI_STACK_SIZE];
  56. long zstack[DVI_STACK_SIZE];
  57.  
  58. /* Stack manipulation: push and pop
  59.  */
  60.  
  61. push()
  62. {
  63.   if (stackptr >= DVI_STACK_SIZE) croak("dvi stack overflow");
  64.   hstack[stackptr] = h;
  65.   h_pixstack[stackptr] = h_pix;
  66.   vstack[stackptr] = v;
  67.   v_pixstack[stackptr] = v_pix;
  68.   wstack[stackptr] = w;
  69.   xstack[stackptr] = x;
  70.   ystack[stackptr] = y;
  71.   zstack[stackptr] = z;
  72.   stackptr++;
  73. }
  74.  
  75. pop()
  76. {
  77.   if (stackptr <= 0) croak("dvi stack underflow");
  78.   stackptr--;
  79.   h = hstack[stackptr];
  80.   h_pix = h_pixstack[stackptr];
  81.   v = vstack[stackptr];
  82.   v_pix = v_pixstack[stackptr];
  83.   w = wstack[stackptr];
  84.   x = xstack[stackptr];
  85.   y = ystack[stackptr];
  86.   z = zstack[stackptr];
  87. }
  88.  
  89. position()
  90. {
  91.   register int dh = h_pix - (h * numerator + half_denominator) / denominator;
  92.   register int dv = v_pix - (v * numerator + half_denominator) / denominator;
  93.  
  94.   if (dh > MAXDRIFT) h_pix -= MAXDRIFT;
  95.   else if (dh < -MAXDRIFT) h_pix += MAXDRIFT;
  96.   if (dv > MAXDRIFT) v_pix -= MAXDRIFT;
  97.   else if (dv < -MAXDRIFT) v_pix += MAXDRIFT;
  98.   dev_position(h_pix,v_pix);
  99. }
  100.  
  101. /* Drawing: set and setrule
  102.  */
  103. set(ch,movep)
  104.      unsigned long ch;
  105.      int movep;
  106. {
  107.   long texwidth,devwidth;
  108.  
  109.   f_use_char(ch,&texwidth,&devwidth);
  110.   position();
  111.   dev_setc(ch,devwidth);
  112.   if (movep) {
  113.     h += texwidth;
  114.     h_pix += devwidth;
  115.   }
  116. }
  117.  
  118. setrule(movep)
  119.      int movep;
  120. {
  121.   long a = sget4(in);
  122.   long b = sget4(in);
  123.   long a_pix,b_pix;
  124.   
  125.   if (a > fntspc || a < -fntspc)
  126.     a_pix = ((v + a) * numerator + half_denominator) / denominator - v_pix;
  127.   else if (a < 0) 
  128.     a_pix = - ((-a * numerator + half_denominator) / denominator);
  129.   else 
  130.     a_pix = (a * numerator + half_denominator) / denominator;
  131.   if (b > fntspc || b < -fntspc) 
  132.     b_pix = ((h + b) * numerator + half_denominator) / denominator - h_pix;
  133.   else if (b < 0) 
  134.     b_pix = - ((-b * numerator + half_denominator) / denominator);
  135.   else 
  136.     b_pix = (b * numerator + half_denominator) / denominator;
  137.   if (a_pix > 0 && b_pix > 0) {
  138.     position();
  139.     dev_draw_box(a_pix,b_pix);
  140.   }
  141.   if (movep) {
  142.     h += b;
  143.     h_pix += b_pix;
  144.   }
  145. }
  146.  
  147. /* Movement: right and down
  148.  */
  149.  
  150. right(dx)
  151.      long dx;
  152. {
  153.   h += dx;
  154.   if (dx > fntspc || dx < -fntspc * 4) 
  155.     h_pix = (h * numerator + half_denominator) / denominator;
  156.   else if (dx < 0) 
  157.     h_pix -= (-dx * numerator + half_denominator) / denominator;
  158.   else 
  159.     h_pix += (dx * numerator + half_denominator) / denominator;
  160. }
  161.  
  162. down(dy)
  163.      long dy;
  164. {
  165.   v += dy;
  166.   if (dy > fntspc * 5) 
  167.     v_pix = (v * numerator + half_denominator) / denominator;
  168.   else if (dy < 0) 
  169.     v_pix -= (-dy * numerator + half_denominator) / denominator;
  170.   else 
  171.     v_pix += (dy * numerator + half_denominator) / denominator;
  172. }
  173.  
  174.  
  175. /* Special: xxx
  176.  */
  177. xxx(k)
  178.      long k;
  179. {
  180.   position();
  181.   dev_special(k,in);
  182. }
  183.  
  184.  
  185. /* Fonts: fntdef
  186.  */
  187. fntdef(fontnum)
  188.      unsigned long fontnum;
  189. {
  190.   unsigned long tfmchecksum = get4(in);
  191.   long s = sget4(in);
  192.   long d = sget4(in);
  193.   int a = get1(in);
  194.   int l = get1(in);
  195.   int i;
  196.   char area[257];
  197.   char name[257];
  198.   long mag;
  199.  
  200.   for (i = 0; i < a; i++) area[i] = getc(in); area[a] = 0;
  201.   for (i = 0; i < l; i++) name[i] = getc(in); name[l] = 0;
  202.   mag = s * globalmag / d;
  203.   debug("fntdef: num= %d area=\"%s\" name=\"%s\" mag=%d s=%d\n",
  204.     fontnum,area,name,mag,s);
  205.   f_define_font(fontnum,0,area,name,mag,s,tfmchecksum);
  206. }
  207.  
  208. /* Fonts: fntdef
  209.  */
  210. nullfntdef(fontnum)
  211.      unsigned long fontnum;
  212. {
  213.   register int a,l,i;
  214.  
  215.   (void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
  216.   (void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
  217.   (void) getc(in); (void) getc(in); (void) getc(in); (void) getc(in);
  218.   a = getc(in);
  219.   l = getc(in);
  220.   for (i = 0; i < a; i++) (void) getc(in);
  221.   for (i = 0; i < l; i++) (void) getc(in);
  222. }
  223.  
  224. /* Record this font number on fntvec
  225.  * We'll later pass fntvec to the fonts module 
  226.  */
  227. int fntmark(fnt)
  228.      unsigned long fnt;
  229. {
  230.   register int i;
  231.  
  232.   for (i = 0; i < fntveclen; i++) if (fntvec[i] == fnt) return(i);
  233.   if (fntveclen >= sizeof(fntvec)) croak("too many fonts");
  234.   chrvec[fntveclen][0] = 0;
  235.   chrvec[fntveclen][1] = 0;
  236.   chrvec[fntveclen][2] = 0;
  237.   chrvec[fntveclen][3] = 0;
  238.   fntvec[fntveclen] = fnt;
  239.   return(fntveclen++);
  240. }
  241.  
  242. chrmark(ch,i)
  243.      unsigned long ch;
  244.      int i;
  245. {
  246.   chrvec[i][ch/32] |= (1 << (ch % 32));
  247. }
  248.  
  249. /* End of page processing: eop
  250.  */
  251. eop()
  252. {
  253.   dev_eop();
  254. }
  255.  
  256. noprint_page(c,p)
  257.      long c[10];
  258.      long p;
  259. {
  260.   int f;
  261.   register int ch;
  262.  
  263.   (void) c; (void) p;
  264.   fntveclen = 0;
  265.   for (;;) {
  266.     if (ferror(in)) croak("noprint_page dvi input");
  267.     switch (ch = getc(in)) {
  268.     case SETRULE:
  269.     case PUTRULE:
  270.       (void) getc(in);
  271.       (void) getc(in);
  272.       (void) getc(in);
  273.       (void) getc(in);
  274.  
  275.     case RIGHT4:
  276.     case W4:
  277.     case DOWN4:
  278.     case X4:
  279.     case Y4:
  280.     case Z4:
  281.       (void) getc(in);
  282.  
  283.     case RIGHT3:
  284.     case W3:
  285.     case X3:
  286.     case DOWN3:
  287.     case Y3:
  288.     case Z3:
  289.       (void) getc(in);
  290.  
  291.     case RIGHT2:
  292.     case W2:
  293.     case X2:
  294.     case DOWN2:
  295.     case Y2:
  296.     case Z2:
  297.       (void) getc(in);
  298.  
  299.     case RIGHT1:
  300.     case W1:
  301.     case X1:
  302.     case DOWN1:
  303.     case Y1:
  304.     case Z1:
  305.       (void) getc(in);
  306.  
  307.     case NOP:
  308.     case PUSH:
  309.     case POP:
  310.     case W0:
  311.     case X0:
  312.     case Y0:
  313.     case Z0:
  314.       break;
  315.  
  316.     case EOP:
  317.       return;
  318.  
  319.  
  320.     case SET1:
  321.     case PUT1:        chrmark(get1(in),f);    break;
  322.     case SET2:
  323.     case PUT2:        chrmark(get2(in),f);    break;
  324.     case SET3:
  325.     case PUT3:        chrmark(get3(in),f);    break;
  326.     case SET4:
  327.     case PUT4:        chrmark(get4(in),f);    break;
  328.     case FNT1:        f = fntmark(get1(in));    break;
  329.     case FNT2:        f = fntmark(get2(in));    break;
  330.     case FNT3:        f = fntmark(get3(in));    break;
  331.     case FNT4:        f = fntmark(get4(in));    break;
  332.     case FNTDEF1:    nullfntdef(get1(in));    break;
  333.     case FNTDEF2:    nullfntdef(get2(in));    break;
  334.     case FNTDEF3:    nullfntdef(get3(in));    break;
  335.     case FNTDEF4:    nullfntdef(get4(in));    break;
  336.     case XXX1:        swallow(get1(in),in);    break;
  337.     case XXX2:        swallow(get2(in),in);    break;
  338.     case XXX3:        swallow(get3(in),in);    break;
  339.     case XXX4:        swallow(get4(in),in);    break;
  340.             
  341.     case EOF:
  342.       croak("noprint_page EOF between BOP and EOP");
  343.       break;
  344.  
  345.     default:
  346.       if (ch >= SETCHAR0 && ch <= SETCHAR127)
  347.     chrmark((unsigned long) (ch - SETCHAR0),f);
  348.       else if (ch >= FNTNUM0 && ch <= FNTNUM63)
  349.     f = fntmark((unsigned long) (ch - FNTNUM0));
  350.       else croak("noprint_page dvi command %d between BOP and EOP",ch);
  351.       break;
  352.     }
  353.   }
  354. }
  355.  
  356. print_page(c,p)
  357.      long c[10];
  358.      long p;
  359. {
  360.   long ch;
  361.  
  362.   (void) p;
  363.   stackptr = 0;
  364.   h = v = w = x = y = z = h_pix = v_pix = 0;
  365.   position();
  366.   for (;;) {
  367.     if (ferror(in)) croak("print_page dvi input");
  368.     switch (ch = getc(in)) {
  369.     case EOF:
  370.       croak("print_page EOF between BOP and EOP");
  371.       break;
  372.  
  373.     case SET1:        set(get1(in),1);    break;
  374.     case SET2:        set(get2(in),1);    break;
  375.     case SET3:        set(get3(in),1);    break;
  376.     case SET4:        set(get4(in),1);    break;
  377.     case SETRULE:    setrule(1);        break;
  378.     case PUT1:        set(get1(in),0);    break;
  379.     case PUT2:        set(get2(in),0);    break;
  380.     case PUT3:        set(get3(in),0);    break;
  381.     case PUT4:        set(get4(in),0);    break;
  382.     case PUTRULE:    setrule(0);        break;
  383.     case NOP:                    break;
  384.     case EOP:        eop();            return;
  385.     case PUSH:        push();            break;
  386.     case POP:        pop();            break;
  387.     case RIGHT1:    right(sget1(in));    break;
  388.     case RIGHT2:    right(sget2(in));    break;
  389.     case RIGHT3:    right(sget3(in));    break;
  390.     case RIGHT4:    right(sget4(in));    break;
  391.     case W0:        right(w);        break;
  392.     case W1:        right(w = sget1(in));    break;
  393.     case W2:        right(w = sget2(in));    break;
  394.     case W3:        right(w = sget3(in));    break;
  395.     case W4:        right(w = sget4(in));    break;
  396.     case X0:        right(x);        break;
  397.     case X1:        right(x = sget1(in));    break;
  398.     case X2:        right(x = sget2(in));    break;
  399.     case X3:        right(x = sget3(in));    break;
  400.     case X4:        right(x = sget4(in));    break;
  401.     case DOWN1:        down(sget1(in));    break;
  402.     case DOWN2:        down(sget2(in));    break;
  403.     case DOWN3:        down(sget3(in));    break;
  404.     case DOWN4:        down(sget4(in));    break;
  405.     case Y0:        down(y);        break;
  406.     case Y1:        down(y = sget1(in));    break;
  407.     case Y2:        down(y = sget2(in));    break;
  408.     case Y3:        down(y = sget3(in));    break;
  409.     case Y4:        down(y = sget4(in));    break;
  410.     case Z0:        down(z);        break;
  411.     case Z1:        down(z = sget1(in));    break;
  412.     case Z2:        down(z = sget2(in));    break;
  413.     case Z3:        down(z = sget3(in));    break;
  414.     case Z4:        down(z = sget4(in));    break;
  415.     case FNT1:        f_use_font(get1(in),&fntspc);    break;
  416.     case FNT2:        f_use_font(get2(in),&fntspc);    break;
  417.     case FNT3:        f_use_font(get3(in),&fntspc);    break;
  418.     case FNT4:        f_use_font(get4(in),&fntspc);    break;
  419.     case FNTDEF1:    nullfntdef(get1(in));    break;
  420.     case FNTDEF2:    nullfntdef(get2(in));    break;
  421.     case FNTDEF3:    nullfntdef(get3(in));    break;
  422.     case FNTDEF4:    nullfntdef(get4(in));    break;
  423.     case XXX1:        xxx(get1(in));        break;
  424.     case XXX2:        xxx(get2(in));        break;
  425.     case XXX3:        xxx(get3(in));        break;
  426.     case XXX4:        xxx(get4(in));        break;
  427.  
  428.     default:
  429.       if (ch >= SETCHAR0 && ch <= SETCHAR127)
  430.     set((unsigned long) (ch - SETCHAR0),1);
  431.       else if (ch >= FNTNUM0 && ch <= FNTNUM63)
  432.     f_use_font((unsigned long) (ch - FNTNUM0),&fntspc);
  433.       else croak("print_page dvi command %d between BOP and EOP",ch);
  434.       break;
  435.     }
  436.   }
  437. }
  438.  
  439. /* Preamble processing.
  440.  */
  441. computescale()
  442. {
  443.   double dd;
  444.  
  445.   /* Compute scale factors for this file. */
  446.   if (usermag) globalmag = usermag; else globalmag = dvimag;
  447.  
  448.   /* This is real hokey, but will probably work for TEX82. */
  449.   if (dvinum != 25400000 || dviden != 473628672) {
  450.     fprintf(stderr,"DVI file numerator and denominator weren't exactly ");
  451.     fprintf(stderr,"what was expected.\nScaling may be wrong.\n");
  452.   }
  453.   numerator = ((long) (((double) dvinum)
  454.                / ((double) 254000)
  455.                / ((double) 10)));
  456.   denominator = ((long) (((double) dviden)
  457.              / ((double) globalmag)
  458.              * ((double) 1000)
  459.              / ((double) device_dpi)
  460.              / ((double) 10)));
  461.   half_denominator = denominator / 2;
  462.   debug("Computescale: globalmag=%d numerator=%d denominator=%d\n",
  463.     globalmag,numerator,denominator);
  464.                 
  465. }
  466.  
  467.  
  468. preamble()
  469. {
  470.   int i = getc(in);
  471.   int k;
  472.  
  473.   dvinum = get4(in);
  474.   dviden = get4(in);
  475.   dvimag = get4(in);
  476.   k = get1(in);
  477.   if (i != 2) croak("id_byte=%d, probably not a dvi file",i);
  478.   for (i = 0; i < k; i++) pre_comment[i] = getc(in);
  479.   pre_comment[k] = '\0';
  480.   computescale();
  481.   debug("Preamble: dvinum=%d dviden=%d dvimag=%d usermag=%d\n",
  482.     dvinum,dviden,dvimag,usermag);
  483.   debug("          comment: \"%s\"\n",pre_comment);
  484. }
  485.  
  486. /* Beginning of page processing
  487.  */
  488. bop()
  489. {
  490.   int i;
  491.   long c[10];
  492.   long p,fpos;
  493.   
  494.   for (i = 0; i < 10; i++) c[i] = sget4(in);
  495.   p = sget4(in);
  496.   if (start_page <= c[0] && c[0] <= end_page) {
  497.     debug("first pass of page %d\n",c[0]);
  498.     fpos = ftell(in);        /* Remember where we are */
  499.     noprint_page(c,p);        /* First pass noprint to get fntvec */
  500.     /* Tell font module about the fonts */
  501.     f_newpage(fntvec,chrvec,fntveclen);
  502.     debug("second pass of page %d\n",c[0]);
  503.     fseek(in,fpos,0);        /* Back up */
  504.     print_page(c,p);        /* And finally do the page */
  505.     debug("done with page %d\n",c[0]);
  506.   } else noprint_page(c,p);
  507. }
  508.  
  509. /* Postamble processing.
  510.  */
  511.  
  512. find_postamble()
  513. {
  514.   int ch;
  515.   long i = -4;
  516.   long q;
  517.  
  518.   do (void) fseek(in,i--,2); while ((ch = getc(in)) == TRAILER);
  519.   if (ch != 2) croak("postamble id_byte=%d, probably not a dvi file",ch);
  520.   (void) fseek(in,i-4,2); 
  521.   if ((ch = getc(in)) != POSTPOST) croak("no POSTPOST where expected");  
  522.   q = sget4(in);
  523.   (void) fseek(in,q,0);
  524.   if ((ch = getc(in)) != POST) croak("no POST where expected");  
  525. }
  526.  
  527.  
  528. postamble()
  529. {
  530.   int ch;
  531.   long p = sget4(in);
  532.   unsigned long l,u,maxstackdepth,npages;
  533.  
  534.   dvinum = get4(in);
  535.   dviden = get4(in);
  536.   dvimag = get4(in);
  537.   computescale();
  538.   l = get4(in);
  539.   u = get4(in);
  540.   maxstackdepth = get2(in);
  541.   npages = get2(in);
  542.   debug("Postamble: dvinum=%d dviden=%d dvimag=%d maxstackdepth=%d\n",
  543.     dvinum,dviden,dvimag,maxstackdepth);
  544.   debug("           npages=%d\n",npages);
  545.   if (maxstackdepth > DVI_STACK_SIZE)
  546.     croak("dvi file has too much stack depth");
  547.   f_init(out,pgmnam,dirvec,dirveclen,numerator
  548.      ,denominator,globalmag,fontopts);
  549.   for (;;) {
  550.     if (ferror(in)) croak("postamble input");
  551.     switch (ch = getc(in)) {
  552.     case EOF:
  553.       croak("EOF found before POSTPOST");
  554.       break;
  555.  
  556.     case FNTDEF1:    fntdef(get1(in));    break;
  557.     case FNTDEF2:    fntdef(get2(in));    break;
  558.     case FNTDEF3:    fntdef(get3(in));    break;
  559.     case FNTDEF4:    fntdef(get4(in));    break;
  560.     case NOP:                    break;
  561.     case POSTPOST:                return;
  562.               
  563.     default:
  564.       croak("dvi command %d in postamble",ch);
  565.       break;            
  566.     }
  567.   }  
  568. }
  569.  
  570. /* Process a dvi file
  571.  */
  572. file_init()
  573. {
  574.   int ch;
  575.  
  576.   if ((ch = getc(in)) != PRE) 
  577.     croak("first char %d not PRE, probably not a dvi file",ch);
  578.   find_postamble();
  579.   dev_init(out,devopts,&device_dpi);
  580.   open_ef();
  581.   postamble();
  582.   (void) fseek(in,1L,0);
  583.   preamble();
  584. }
  585.  
  586. file_term()
  587. {
  588.   f_term();
  589.   close_ef();
  590.   dev_term();
  591. }
  592.  
  593. dvi_file()
  594. {
  595.   int ch;
  596.  
  597.   if (!dirveclen) dirvec[dirveclen++] = PXLDIR;
  598.   file_init();
  599.   for (;;) {
  600.     if (ferror(in)) croak("dvi_file input");
  601.     switch (ch = getc(in)) {
  602.     case EOF:
  603.       croak("EOF found between pages");
  604.       break;
  605.  
  606.     case BOP:        bop();            break;
  607.     case POST:        file_term();        return;
  608.     case FNTDEF1:    fntdef(get1(in));    break;
  609.     case FNTDEF2:    fntdef(get2(in));    break;
  610.     case FNTDEF3:    fntdef(get3(in));    break;
  611.     case FNTDEF4:    fntdef(get4(in));    break;
  612.     case NOP:                    break;
  613.               
  614.     default:
  615.       croak("dvi command %d between pages",ch);
  616.       break;            
  617.     }
  618.   }
  619. }
  620.  
  621. process_stdin()
  622. {
  623.   int ch;
  624.   FILE *tf;
  625.   char tfn[257];
  626.   struct stat st;
  627.  
  628.   if (fstat(fileno(stdin),&st) < 0) croak("can't stat stdin");
  629.   if ((st.st_mode & S_IFMT) == S_IFREG) {
  630.     in = stdin; infname = "stdin";
  631.     dvi_file();
  632.     in = NULL; infname = NULL;
  633.   } else {
  634.     /* Copy the dvi data to a temp file, since we have to do disk seeks. */
  635.     (void) sprintf(tfn,"/usr/tmp/%s.XXXXXX",pgmnam);
  636.     if (!(tf = fopen(mktemp(tfn),"w"))) croak("couldn't open %s",tfn);
  637.     unlink(tfn);
  638.     while (!ferror(stdin) && (ch = getchar()) != EOF) putc(ch,tf);
  639.     if (ferror(stdin)) croak("error on stdin");
  640.     (void) fseek(tf,0L,0);
  641.     infname = tfn; in = tf;
  642.     dvi_file();
  643.     in = NULL; infname = NULL;
  644.     (void) fclose(tf); 
  645.   }
  646. }
  647.  
  648. main(argc,argv)
  649.      int argc;
  650.      char *argv[];
  651. {
  652.   FILE *f;
  653.   int nfiles = 0;
  654.   int i;
  655.   
  656.   setbuf(stdout,stdoutbuf);
  657.   pgmnam = argv[0];
  658.   fontopts = 0;
  659.   devopts = 0;
  660.  
  661.   for (i = 1; i < argc; i++)
  662.     if (argv[i][0] == '-') switch(argv[i][1]) {
  663.     case '8':
  664.       fontopts |= F_INIT_QMS800;
  665.       break;
  666.  
  667.     case 'd':
  668.       debugging++;
  669.       break;
  670.  
  671.     case 'f':
  672.       start_page = atoi((argv[i][2])? argv[i]+2 : argv[++i]);
  673.       break;
  674.  
  675.     case 'h':
  676.       host = argv[++i];
  677.       break;
  678.  
  679.     case 'l':
  680.       devopts |= DEV_INIT_LANDSCAPE;
  681.       fontopts |= F_INIT_LANDSCAPE;
  682.       break;
  683.  
  684.     case 'm':
  685.       usermag = atoi((argv[i][2])? argv[i]+2 : argv[++i]);
  686.       break;
  687.  
  688.     case 'n':
  689.       user = argv[++i];
  690.       break;
  691.  
  692.     case 'o':
  693.       if (f = fopen(argv[++i],"w")) {
  694.     if (out != stdout) (void) fclose(out);
  695.     out = f; outfname = argv[i];
  696.     f = NULL;
  697.       }
  698.       break;
  699.       
  700.     case 't':
  701.        end_page = atoi((argv[i][2])? argv[i]+2 : argv[++i]);
  702.       break;
  703.  
  704.     case 'x':
  705.     case 'y':
  706.       break;
  707.  
  708.     default:
  709.       croak("bad switch: %s",argv[i]);
  710.       break;
  711.   } else {
  712.     nfiles++;
  713.     if (f = fopen(argv[i],"r")) {
  714.       in = f; infname = argv[i];
  715.       dvi_file();
  716.       (void) fclose(f);
  717.     } else croak("couldn't open %s",argv[i]);
  718.   }
  719.   /* If I'm a lpd filter, see if I'm for a qms800 */
  720.   if (user && host && (out == stdout) && !nfiles && !access("qms800",0))
  721.     fontopts |= F_INIT_QMS800;
  722.   if (!nfiles) process_stdin();
  723.   exit(0);
  724. }
  725.